Implement the agent loop
title: "Build Your Own Redis, Git & SQLite From Scratch" source: "https://app.codecrafters.io/courses/claude-code/stages/ff2" author: published: created: 2026-05-31 description: "Advanced programming challenges for experienced engineers. Rebuild real production tools like Redis, Git, and SQLite from scratch in your IDE." tags: - "clippings"
Implement the agent loop #ff2
In-progress
Stage #ff2
In-progress
Your Task¶
In-progress
Medium
In this stage, you'll implement an agent loop.
The Agent Loop¶
So far, your program handles a single interaction: send a prompt to the LLM, get a response, execute one tool if requested, and exit.
This works for simple tasks, but falls short when the task requires multiple steps (e.g., "read a file and fix any bugs").
For this stage, you'll implement an agent loop that repeatedly sends messages to the model and handles tool calls as needed, until the final result is received.
Here's the structure in pseudocode:
messages = [{ role: "user", content: prompt }]
loop:
response = call_api(messages)
append response message to messages
if response has no tool_calls:
print response.content
exit
for each tool_call in response.tool_calls:
result = execute_tool(tool_call)
append {
role: "tool",
tool_call_id: tool_call.id,
content: result
} to messages
Let's walk through each part of this loop:
- Initialize the conversation: You already have an initial conversation history: the
messagesarray with the user's prompt. Now you need to store this array so it can persist across iterations, since the loop will continuously append new messages to it:js [ { "role": "user", "content": "Summarize the README for me." } ] - Enter the loop: Start the loop with the same API request you already have (sending your
messagesand tool specifications to the model). The difference is that this request now sits in a loop, allowing it to run multiple times. - Record the assistant's response: Whatever message the model returns, add it to your
messagesarray. If the model wants to use a tool, the response will contain atool_callsarray:js { "role": "assistant", "content": null, "tool_calls": [ { "id": "call_abc123", "type": "function", "function": { "name": "Read", "arguments": "{\"file_path\": \"README.md\"}" } } ] } - Execute tool calls: Check the model's response to see if it's requesting to use any tools. If tool calls are present:
- a. Execute each requested tool (but do not print their result to stdout).
- b. Add each tool call result to your
messagesarray. Every tool result must: - Have the
rolefield set to"tool"- Reference the correspondingtool_call_id- Include the tool call result as itscontentjs { "role": "tool", "tool_call_id": "call_abc123", "content": "# My Project\n\nChemical expiry period: 6 months" }
- b. Add each tool call result to your
- a. Execute each requested tool (but do not print their result to stdout).
- Repeat until complete: Continue the loop until the model responds without requesting any tools (when
tool_callsis missing or empty). At this point, print the final messagecontentto stdout and exit.
Tests¶
The tester will create a Python project with:
README.md- Two Python files in
app/with randomized names
The tester will then execute your program like this:
$ ./your_program.sh -p "Use README.md to determine the chemical expiry period in months. Number only."
<expiry period in months>
The tester will verify that:
- The output is the correct expiry period
- Your program exits with exit code
0
Notes¶
- Do not print raw file contents when executing the Read tool. This differs from the behavior in the “Execute the read tool” stage.
- You can print intermediate debugging information to stderr. Print to stdout only when the final result is ready to be printed.
- You can also use
finish_reason: "stop"from the first response choice as a signal to stop the loop.
How to pass this stage¶
1
Write code to pass this stage
Head over to your editor / IDE and implement your solution.
If you want a quick look at what functions to use or how to structure your code, we recommend looking at Code Examples.
2
Submit code
To run tests, make changes to your code and run the submit command:
codecrafters submit # Visit https://codecrafters.io/cli to install
Test Runner:
Ready to run tests
Hints¶
Filter by Python
Write
Preview
Complete this stage to hit #10569
Ready to run tests
Show logs